/*
装饰器模式（Decorator Pattern）是一种结构型设计模式，它允许在不改变已有对象结构的情况下，动态地给对象添加额外的行为。
装饰器模式通过创建一个包装器（Wrapper）来包裹原始对象，然后在包装器中添加额外的行为。
这样，可以通过嵌套多个装饰器来实现对对象的多层次装饰。

装饰器模式的主要角色包括：

● 抽象构件（Component）：定义了原始对象和装饰器对象的共同接口。
● 具体构件（Concrete Component）：实现了抽象构件接口，是被装饰的原始对象。
● 抽象装饰器（Decorator）：继承了抽象构件接口，并持有一个抽象构件对象的引用，用于包装原始对象。
● 具体装饰器（Concrete Decorator）：继承了抽象装饰器接口，实现了装饰器的具体功能。

使用装饰器模式可以实现动态地给对象添加功能，同时避免了使用继承来扩展对象功能所带来的静态特性。
装饰器模式符合开闭原则，使得系统更加灵活，易于扩展和维护。

下面是一个使用装饰器模式的C语言例程，用于实现一个咖啡店的订单系统，其中咖啡是原始对象，而调料（如牛奶、糖等）是装饰器对象，可以动态地给咖啡添加调料：
*/

#include <stdio.h>
#include <stdlib.h>

// 抽象构件
typedef struct
{
    char *description; // 描述
    double cost;       // 费用
    void (*print)();
} Beverage; // 饮料

// 具体构件
typedef struct
{
    Beverage beverage; // 饮料
    void (*print)();
} Coffee;

// 抽象装饰器
typedef struct
{
    Beverage *beverage;
    void (*print)();
} CondimentDecorator;

// 具体装饰器
typedef struct
{
    CondimentDecorator condimentDecorator;
    void (*print)();
} Milk;

typedef struct
{
    CondimentDecorator condimentDecorator;
    void (*print)();
} Sugar;

// 打印咖啡信息
void printBeverage(Beverage *beverage)
{
    // Beverage *beverage = (Beverage *)malloc(sizeof(Beverage));
    printf("Description: %s\n", beverage->description);
    printf("Cost: $%.2f\n", beverage->cost);
}

// 打印调料信息
void printCondiment(CondimentDecorator *condimentDecorator)
{
    // CondimentDecorator *condimentDecorator = (CondimentDecorator *)malloc(sizeof(CondimentDecorator));
    condimentDecorator->beverage->print(condimentDecorator->beverage);
    printf("Description: %s\n", condimentDecorator->beverage->description);
    printf("Cost: $%.2f\n", condimentDecorator->beverage->cost);
}

int main()
{
    // 创建咖啡和调料
    Coffee coffee;
    coffee.beverage.description = "Coffee";
    coffee.beverage.cost = 1.99;
    coffee.beverage.print = printBeverage;

    Milk milk;
    milk.condimentDecorator.beverage = /*(Beverage *)*/ &(coffee.beverage);
    milk.condimentDecorator.print = printCondiment;

    Sugar sugar;
    sugar.condimentDecorator.beverage = /*(Beverage *)*/ milk.condimentDecorator.beverage;
    sugar.condimentDecorator.print = printCondiment;

    // 使用装饰器给咖啡添加调料
    sugar.condimentDecorator.print(&(sugar.condimentDecorator));

    return 0;
}

/*
在上面的例程中，首先定义了抽象构件Beverage，其中声明了打印的接口方法。
然后，实现了具体构件Coffee，其中包含了咖啡的描述和价格，并实现了打印的方法。
接下来，定义了抽象装饰器CondimentDecorator，其中持有一个抽象构件对象的引用，并实现了打印的方法。
然后，实现了具体装饰器Milk和Sugar，分别给咖啡添加了牛奶和糖的功能，并实现了打印的方法。
在main函数中，创建了咖啡和调料对象，并使用装饰器给咖啡添加调料，最后打印出咖啡的描述和价格。

通过使用装饰器模式，我们可以动态地给对象添加额外的行为，而无需改变原始对象的结构。
这样可以使得系统更加灵活，易于扩展和维护。
同时，装饰器模式也符合单一职责原则，每个装饰器只关注自己的功能，使得系统的设计更加清晰。
*/